home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
VISUALBA
/
BOZOL2.ZIP
/
BTREE.BAS
< prev
next >
Wrap
BASIC Source File
|
1994-02-08
|
21KB
|
727 lines
'PUBLIC Act.Keys$, BT.Update.Always%
' be sure that you have the above PUBLIC statement near the top of
' the calling program.
'EXTERNAL Act.Keys$, BT.Update.Always%
' and put this line at the top of this file if you are creating a unit,
' otherwise, PUBLIC and EXTERNAL are not necessary with include files
Sub BT(FileName$,Action$,SKy$,SDta$,RKy$,RDta$,RCCODE%) PUBLIC
Static Keys$(),Ptr$(),Stk%(),Itm$(),Dta$(),LastFile$,Cur.Lvl%,_
Hlf.Node$,Hlf.Node%,Key.Len$,Key.Len%,Dta.Len$,Dta.Len%,_
Itm.Len$,Itm.Len%,CCODE$,Root.Node$,Root.Rec%,Nxt.Node$,_
Nxt.Node%,Lst.Del$,Lst.Del%,Num.Act$,Num.Act%,Num.Keys$,_
Keys.Act%,Itm.Ptr%,Cur.Rec%
%BT.Max.Half.Node = 15
%BT.Max.Node = %BT.Max.Half.Node * 2
%BT.File.Num = 2801
DIM Keys$(0:%BT.Max.Node),Ptr$(0:%BT.Max.Node),Stk%(0:10,0:1),_
Itm$(0:%BT.Max.Node),Dta$(0:%BT.Max.Node)
UsrAct$ = Ucase$(Left$(Action$+" ",1))
If UsrAct$ = "C" Then
Gosub BT.Create
Else
Status% = -1
If UsrAct$ <> "Q" Then
If Ucase$(FileName$) <> Ucase$(LastFile$) then Gosub BT.Open.New
If LastFile$ = "" Then Status% = 0
End if
If Status% Then
Select Case UsrAct$
Case "F" 'Get First Key
Cur.Lvl% = 0
Gosub Bt.Get.Next
Case "L" 'Get Last Key
Cur.Lvl% = 0
Gosub Bt.Get.Prev
Case "S" 'Search for key in Ky$
Ky$ = Sky$
Gosub Bt.Search
Case "A" 'Add a non-unique key
Ky$ = Sky$
Da$ = SDta$
Gosub BT.Add.Non.Unique
Case "U" 'Add a unique key
Ky$ = Sky$
Da$ = Sdta$
Gosub BT.Add.Unique
Case "D" 'Delete the key/data given
Ky$ = Sky$
Gosub BT.Search
Do Until Status% = 0
If Ky$ <> Keys$(Itm.Ptr%) Then
Status% = 0
Exit Loop
End if
If SDta$ = Dta$(Itm.Ptr%) Then
Gosub BT.Del.Cur
Status% = -1
Exit Loop
Else
Gosub BT.Get.Next
End if
Loop
Case "N" 'Get Next Key
Gosub BT.Get.Next
Case "P" 'Get Previous Key
Gosub Bt.Get.Prev
Case "Q"
If LastFile$="" then
Status% = 0
Else
Status% = -1
End if
Case Else 'Error in Action CCODE
Rky$ = ""
RdTmp.Add$= ""
Status% = 0
End Select
End if
If Instr("AUDQ",UsrAct$) And Status% And (BT.Update.Always% or UsrAct$="Q") Then
Gosub BT.Update.Stats
Call UpdateFile(%BT.File.Num)
If UsrAct$ = "Q" Then
Close %BT.File.Num
LastFile$ = ""
End if
End if
End if
Rky$ = Keys$(Itm.Ptr%)
Rdta$= Dta$(Itm.Ptr%)
RCCODE% = Status%
Exit Sub
BT.Open.New:
If LastFile$ <> "" Then Gosub BT.Update.Stats
Close %BT.File.Num
Open FileName$ FOR RANDOM SHARED AS #%BT.File.Num LEN=256
Gosub Bt.Get.Stats
If Status% = 0 Then
LastFile$ = ""
Close %BT.File.Num
Else
LastFile$ = FileName$
Gosub BT.Get.Stats
Gosub Bt.Field.Node
End if
Return
BT.Create:
Close %BT.File.Num
Hlf.Node% = ( (253 \ (Len(SKy$) + Len(SDta$) + 2)) \ 2 )
If Hlf.Node% < 1 Then
Status% = 0
LastFile$ = ""
Return
End if
If Hlf.Node% > %BT.Max.Half.Node then Hlf.Node% = %BT.Max.Half.Node
Open "O",%BT.File.Num,FileName$
Close %BT.File.Num
Open "R",%BT.File.Num,FileName$,256
Gosub BT.Field.Stats
Lset Hlf.Node$ = MKI$(Hlf.Node%)
Lset Key.Len$ = MKI$(Len(SKy$))
Lset Dta.Len$ = MKI$(Len(SDta$))
Lset Itm.Len$ = MKI$(Len(SKy$) + Len(SDta$) + 2)
Lset CCODE$ = "BT"
Lset Root.Node$ = MKI$(2)
Lset Nxt.Node$ = MKI$(3)
Lset Lst.Del$ = MKI$(0)
Lset Num.Act$ = MKI$(1)
Lset Num.Keys$ = MKI$(0)
Put %BT.File.Num,1
Status% = -1
Close %BT.File.Num
LastFile$ = ""
Return
BT.GET.STATS:
GOSUB BT.Field.STATS
If CCODE$ <> "BT" Then
Status% = 0
LastFile$ = ""
Else
Status% = -1
Hlf.Node%=CVI(Hlf.Node$)
Key.Len%=CVI(Key.Len$)
Dta.Len%=CVI(Dta.Len$)
Itm.Len%=CVI(Itm.Len$)
Root.Rec%=CVI(Root.Node$)
Nxt.Node%=CVI(Nxt.Node$)
Lst.Del%=CVI(Lst.Del$)
Num.Act%=CVI(Num.Act$)
Keys.Act%=CVI(Num.Keys$)
End if
RETURN
BT.Field.STATS:
FIELD %BT.File.Num,2 AS Hlf.Node$,2 AS Key.Len$,2 AS Dta.Len$,2 AS Itm.Len$, _
2 AS CCODE$,2 AS Root.Node$,2 AS Nxt.Node$,2 AS Lst.Del$,2 AS Num.Act$,_
2 AS Num.Keys$
Cur.Rec%=1
GOSUB BT.GET.CUR
RETURN
BT.FIELD.NODE:
FIELD %BT.File.Num,1 AS Act.Keys$,2 AS Ptr$(0)
FOR Cnt%=1 TO Hlf.Node%*2
FIELD %BT.File.Num,3+Itm.Len%*(Cnt%-1) AS Tmp2$,(Key.Len%) AS Keys$(Cnt%),_
(Dta.Len%) AS Dta$(Cnt%),2 AS Ptr$(Cnt%)
FIELD %BT.File.Num,3+Itm.Len%*(Cnt%-1) AS Tmp2$,(Itm.Len%) AS Itm$(Cnt%)
NEXT Cnt%
RETURN
BT.GET.STACK.NODE:
Cur.Rec%=Stk%(Cur.Lvl%,0)
Itm.Ptr%=Stk%(Cur.Lvl%,1)
GOSUB BT.GET.CUR
RETURN
BT.POP:
Decr Cur.Lvl%
GOSUB BT.GET.STACK.NODE
RETURN
BT.PUSH:
Stk%(Cur.Lvl%,0)=Cur.Rec%
Stk%(Cur.Lvl%,1)=Itm.Ptr%
RETURN
BT.Update.Stats:
Cur.Rec%=1
GET %BT.File.Num,Cur.Rec%
LSET Root.Node$=MKI$(Root.Rec%)
LSET Nxt.Node$=MKI$(Nxt.Node%)
LSET Lst.Del$=MKI$(Lst.Del%)
LSET Num.Act$=MKI$(Num.Act%)
LSET Num.Keys$=MKI$(Keys.Act%)
PUT %BT.File.Num,Cur.Rec%
RETURN
BT.GET.CUR:
If Cur.Rec% * 256 > Lof(%BT.File.Num) Then
Field %BT.File.Num,256 as Dmy$
Lset Dmy$ = String$(256,0)
Put %BT.File.Num,Cur.Rec%
End if
GET %BT.File.Num,Cur.Rec%
RETURN
'*** SEARCH FOR FIRST OCCURANCE OF KEY ***
BT.SEARCH:
Temp%=0
BT.NON.UNQ:
Status%=0
Cur.Lvl%=1
Cur.Rec%=Root.Rec%
IF LEN(KY$)<>Key.Len% THEN KY$=LEFT$(KY$+STRING$(Key.Len%," "),Key.Len%)
BT.SCAN.NODE:
GOSUB BT.GET.CUR
Itm.Ptr%=1
Cnt%=ASC(Act.Keys$)
BT.S.N.LOOP:
Wrk.Hlf%=INT((Itm.Ptr%+Cnt%)/2)
IF KY$>Keys$(Wrk.Hlf%) OR (Temp%<0 AND KY$=Keys$(Wrk.Hlf%)) THEN_
Itm.Ptr%=Wrk.Hlf%+1 ELSE Cnt%=Wrk.Hlf%-1
IF Cnt%>=Itm.Ptr% THEN
GOTO BT.S.N.LOOP
ELSE
GOSUB BT.PUSH
IF Itm.Ptr%<=ASC(Act.Keys$) THEN
IF KY$=Keys$(Itm.Ptr%) THEN
Status%=-1
IF CVI(Ptr$(Itm.Ptr%-1))=0 THEN RETURN
END IF
END IF
END IF
IF CVI(Ptr$(Itm.Ptr%-1))>0 THEN
Cur.Rec%=CVI(Ptr$(Itm.Ptr%-1))
Incr Cur.Lvl%
GOTO BT.SCAN.NODE
END IF
IF Status% THEN BT.GN.L.SON
If Temp% = 0 Then
Gosub BT.GN.OK
Status% = 0
End if
RETURN
'*** ADD KEY AT CURRENT NODE LOCATION ***
BT.ADD.AT.CUR:
Tmp.Add$=LEFT$(KY$+STRING$(Key.Len%," "),Key.Len%)+LEFT$(DA$+STRING$(Dta.Len%," "),Dta.Len%)+MKI$(0)
Temp%=0
BT.CHK.FULL:
IF ASC(Act.Keys$)<Hlf.Node%*2 THEN
LSET Act.Keys$=CHR$(ASC(Act.Keys$)+1)
Cnt%=ASC(Act.Keys$)
GOSUB BT.INS.IN.NODE
LSET Ptr$(Itm.Ptr%-1)=MKI$(Temp%)
PUT %BT.File.Num,Cur.Rec%
Keys.Act%=Keys.Act%+1
Tmp.Add$=""
Temp$=""
Emerg$=""
Status% = -1
RETURN
END IF
IF Itm.Ptr%>Hlf.Node%+1 THEN
GOTO BT.ADD.RIGHT
ELSEIF Itm.Ptr%=Hlf.Node%+1 Then
Emerg$=Tmp.Add$
ELSE
Emerg$=Itm$(Hlf.Node%)
Cnt%=Hlf.Node%
GOSUB BT.INS.IN.NODE
END IF
LSET Ptr$(Itm.Ptr%-1)=MKI$(Temp%)
LSET Act.Keys$=CHR$(Hlf.Node%)
FIELD %BT.File.Num,3+Hlf.Node%*(Itm.Len%) AS Tmp2$,Hlf.Node%*(Itm.Len%) AS Tmp2$
Temp$=Tmp2$
PUT %BT.File.Num,Cur.Rec%
Temp%=Cur.Rec%
GOSUB BT.GET.AVAIL.NODE
GOSUB BT.SET.COPY
GOSUB BT.SET.RGHT.SON
GOTO BT.WRT.NODE
BT.ADD.RIGHT:
FIELD %BT.File.Num,1 AS Tmp2$,2+Hlf.Node%*(Itm.Len%) AS Tmp2$
Temp$=Tmp2$
Itm.Ptr%=Itm.Ptr%-Hlf.Node%
Emerg$=Itm$(Hlf.Node%+1)
FOR Cnt%=1 TO Itm.Ptr%-2
LSET Itm$(Cnt%)=Itm$(Cnt%+Hlf.Node%+1)
NEXT Cnt%
LSET Itm$(Itm.Ptr%-1)=Tmp.Add$
IF Itm.Ptr%>Hlf.Node% THEN
GOTO BT.SET.LFT.SON
ELSE
FOR Cnt%=Itm.Ptr% TO Hlf.Node%
LSET Itm$(Cnt%)=Itm$(Cnt%+Hlf.Node%)
NEXT Cnt%
END IF
BT.SET.LFT.SON:
GOSUB BT.SET.R